﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using NTmdb.Fakes;
using NTmdb.Net;

namespace NTmdb.TestProject
{
    /// <summary>
    ///     This is a test class for ApiWrapperOfflineTest and is intended
    ///     to contain all ApiWrapperOfflineTest Unit Tests
    /// </summary>
    /// <remarks>
    ///     The test in this class are used to check if the wrapper builds correct queries.
    /// </remarks>
    [TestClass]
    public class ApiWrapperOfflineTest
    {
        #region Properties

        /// <summary>
        ///     Gets or sets a instance of the test target.
        /// </summary>
        /// <value>A instance of the test target.</value>
        public static ApiWrapper Target { get; set; }

        #endregion Properties

        #region Helpers

        /// <summary>
        ///     Creates a new instance of the API Wrapper.
        /// </summary>
        /// <param name="testContext"></param>
        [ClassInitialize]
        public static void MyClassInitialize( TestContext testContext )
        {
            Target = new ApiWrapper
                {
                    ApiClient = new ApiClientNet()
                };
            var config = new ApiConfiguration();
            config.RestoreDefaultValues();
            Target.ApiConfiguration = config;
        }

        /// <summary>
        ///     Gets a fake of <see cref="IApiClient" /> which invokes the given callback when ever GetJson gets called.
        /// </summary>
        /// <param name="getJsonCallback">The callback to invoke. (param0 => URL, param1 => request method)</param>
        /// <returns>
        ///     A fake of <see cref="IApiClient" />
        /// </returns>
        public IApiClient GetFakeClient( Action<String, String> getJsonCallback )
        {
            var client = new StubIApiClient
                {
                    GetJsonAsyncStringITmdbModelBaseStringNullableOfCacheLevelNullableOfTimeSpanNullableOfBoolean =
                        ( url, requestContent, requestMethod, cacheLevel, timeout, useSecureConection ) =>
                            {
                                if ( getJsonCallback != null )
                                    getJsonCallback( url, requestMethod );
                                return null;
                            },
                    GetJsonAsyncStringStringNullableOfCacheLevelNullableOfTimeSpanNullableOfBoolean =
                        ( url, requestMethod, cacheLevel, timeout, useSecureConection ) =>
                            {
                                if ( getJsonCallback != null )
                                    getJsonCallback( url, requestMethod );
                                return null;
                            }
                };
            return client;
        }

        /// <summary>
        ///     Gets a <see cref="ApiWrapper" /> instance, which use a fake API client.
        /// </summary>
        /// <param name="getJsonCallback">The callback to invoke when the wrapper makes an API call. (param0 => URL, param1 => request method)</param>
        /// <returns>
        ///     A <see cref="ApiWrapper" /> instance, which use a fake API client.
        /// </returns>
        public ApiWrapper GetTarget( Action<String, String> getJsonCallback )
        {
            var target = new ApiWrapper();
            var config = new ApiConfiguration();
            config.RestoreDefaultValues( Guid.NewGuid().ToString() );
            target.ApiConfiguration = config;
            target.ApiClient = GetFakeClient( getJsonCallback );
            return target;
        }

        /// <summary>
        ///     Checks if the given URL matches the normal query pattern.
        /// </summary>
        /// <param name="url">The URl to check.</param>
        /// <param name="methodName">The method to which the URl points.</param>
        /// <param name="config">The tmdbConfiguration of the API wrapper.</param>
        public void CheckApiQuery( String url, String methodName, IApiConfiguration config, Dictionary<String, String> queryParameters = null )
        {
            var expected = String.Format( "{0}/{1}?{2}={3}", config.ApiUrl, methodName, config.ApiKeyParameterName, config.ApiKey );
            Assert.IsTrue( url.StartsWith( expected ) );

            var parameters = HttpUtility.ParseQueryString( new Uri( url ).Query );
            Assert.IsTrue( parameters.Count > 0, "API key is missing!" );
            Assert.AreEqual( config.ApiKey, parameters.Get( config.ApiKeyParameterName ) );

            if ( queryParameters == null )
                return;
            Assert.AreEqual( queryParameters.Count + 1, parameters.Count );
            foreach ( var parameter in queryParameters )
                Assert.AreEqual( parameter.Value, parameters.Get( parameter.Key ) );
        }

        #endregion Helpers

        /// <summary>
        ///     A test for ApiWrapper Constructor
        /// </summary>
        [TestMethod]
        public void ApiWrapperConstructorTest()
        {
            var target = new ApiWrapper();
            Assert.IsNotNull( target ); //Just that the method contains a assert....
        }

        #region Configuration

        /// <summary>
        ///     A test for GetConfigurationAsync
        /// </summary>
        [TestMethod]
        public async Task GetConfigurationAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            await target.GetConfigurationAsync();

            CheckApiQuery( url, target.ApiConfiguration.ConfigurationMethodName, target.ApiConfiguration );
            Assert.IsNull( method );
        }

        #endregion Configuration

        #region Authentication

        /// <summary>
        ///     A test for GetAuthenticationTokenAsync
        /// </summary>
        [TestMethod]
        public async Task GetAuthenticationTokenAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            await target.GetAuthenticationTokenAsync();

            CheckApiQuery( url, target.ApiConfiguration.NewAuthenticationTokenMethodName, target.ApiConfiguration );
            Assert.IsNull( method );
        }

        /// <summary>
        ///     A test for GetSessionAsync
        /// </summary>
        [TestMethod]
        public async Task GetSessionAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var token = Guid.NewGuid().ToString();
            await target.GetSessionAsync( token );

            CheckApiQuery( url, target.ApiConfiguration.NewSessionMethodName, target.ApiConfiguration, new Dictionary<string, string>
                {
                    {
                        target.ApiConfiguration.AuthenticationTokenParameterName, token
                    }
                } );
            Assert.IsNull( method );
        }

        /// <summary>
        ///     A test for GetGuestSessionAsync
        /// </summary>
        [TestMethod]
        public async Task GetGuestSessionAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            await target.GetGuestSessionAsync();

            CheckApiQuery( url, target.ApiConfiguration.NewGuestSessionMethodName, target.ApiConfiguration );
            Assert.IsNull( method );
        }

        #endregion Authentication

        #region Account

        /// <summary>
        ///     A test for GetAccountAsync
        /// </summary>
        [TestMethod]
        public async Task GetAccountAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var sessionId = Guid.NewGuid().ToString();
            await target.GetAccountAsync( sessionId );

            CheckApiQuery( url, target.ApiConfiguration.AccountMethodName, target.ApiConfiguration, new Dictionary<String, String>
                {
                    {
                        target.ApiConfiguration.SessionIdParameterName, sessionId
                    }
                } );
            Assert.IsNull( method );
        }

        /// <summary>
        ///     A test for GetAccountListsAsync
        /// </summary>
        [TestMethod]
        public async Task GetAccountListsAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var sessionId = Guid.NewGuid().ToString();
            var accountId = new Random().Next( 0, Int32.MaxValue );
            var page = new Random().Next( 0, Int32.MaxValue );
            var langauge = Guid.NewGuid().ToString();

            await target.GetAccountListsAsync( accountId, sessionId, page, langauge );

            CheckApiQuery( url, String.Format( target.ApiConfiguration.AccountListsMethodName, accountId ), target.ApiConfiguration,
                           new Dictionary<String, String>
                               {
                                   {
                                       target.ApiConfiguration.SessionIdParameterName, sessionId
                                   },
                                   {
                                       target.ApiConfiguration.PageParameterName, page.ToString()
                                   },
                                   {
                                       target.ApiConfiguration.LanguageParameterName, langauge
                                   },
                               } );
            Assert.IsNull( method );
        }

        /// <summary>
        ///     A test for SetFavoriteAsync
        /// </summary>
        [TestMethod]
        public async Task SetFavoriteAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var sessionId = Guid.NewGuid().ToString();
            var accountId = new Random().Next( 0, Int32.MaxValue );

            await target.SetFavoriteAsync( accountId, new TmdbFavoriteRequest(), sessionId );

            CheckApiQuery( url, String.Format( target.ApiConfiguration.AccountAddFavoriteMethodName, accountId ), target.ApiConfiguration,
                           new Dictionary<String, String>
                               {
                                   {
                                       target.ApiConfiguration.SessionIdParameterName, sessionId
                                   }
                               } );
            Assert.IsNull( method );
        }

        /// <summary>
        ///     A test for SetWatchListAsync
        /// </summary>
        [TestMethod]
        public async Task SetWatchListAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var sessionId = Guid.NewGuid().ToString();
            var accountId = new Random().Next( 0, Int32.MaxValue );

            await target.SetWatchListAsync( accountId, new TmdbWatchListRequest(), sessionId );

            CheckApiQuery( url, String.Format( target.ApiConfiguration.AccountEditWatchListMethodName, accountId ), target.ApiConfiguration,
                           new Dictionary<String, String>
                               {
                                   {
                                       target.ApiConfiguration.SessionIdParameterName, sessionId
                                   }
                               } );
            Assert.IsNull( method );
        }

        /// <summary>
        ///     A test for GetAccountFavoriteMoviesAsync
        /// </summary>
        [TestMethod]
        public async Task GetAccountFavoriteMoviesAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var sessionId = Guid.NewGuid().ToString();
            var accountId = new Random().Next( 0, Int32.MaxValue );
            var page = new Random().Next( 0, Int32.MaxValue );
            const TmdbSortBy sortBy = TmdbSortBy.CreatedAt;
            var sortOrder = page % 2 == 0 ? TmdbSortOrder.Ascending : TmdbSortOrder.Descending;
            var language = Guid.NewGuid().ToString();

            await target.GetAccountFavoriteMoviesAsync( accountId, sessionId, page, sortBy, sortOrder, language );

            CheckApiQuery( url, String.Format( target.ApiConfiguration.AccountFavoriteMoviesMethodName, accountId ), target.ApiConfiguration,
                           new Dictionary<String, String>
                               {
                                   {
                                       target.ApiConfiguration.SessionIdParameterName, sessionId
                                   },
                                   {
                                       target.ApiConfiguration.PageParameterName, page.ToString( CultureInfo.InvariantCulture )
                                   },
                                   {
                                       target.ApiConfiguration.SortByParameterName, sortBy.ToTmdbParameter( target.ApiConfiguration )
                                   },
                                   {
                                       target.ApiConfiguration.SortOrderParameterName, sortOrder.ToTmdbParameter( target.ApiConfiguration )
                                   },
                                   {
                                       target.ApiConfiguration.LanguageParameterName, language
                                   }
                               } );
            Assert.IsNull( method );
        }

        /// <summary>
        ///     A test for GetAccountRatedMoviesAsync
        /// </summary>
        [TestMethod]
        public async Task GetAccountRatedMoviesAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var sessionId = Guid.NewGuid().ToString();
            var accountId = new Random().Next( 0, Int32.MaxValue );
            var page = new Random().Next( 0, Int32.MaxValue );
            const TmdbSortBy sortBy = TmdbSortBy.CreatedAt;
            var sortOrder = page % 2 == 0 ? TmdbSortOrder.Ascending : TmdbSortOrder.Descending;
            var language = Guid.NewGuid().ToString();

            await target.GetAccountRatedMoviesAsync( accountId, sessionId, page, sortBy, sortOrder, language );

            CheckApiQuery( url, String.Format( target.ApiConfiguration.AccountRatedMoviesMethodName, accountId ), target.ApiConfiguration,
                           new Dictionary<String, String>
                               {
                                   {
                                       target.ApiConfiguration.SessionIdParameterName, sessionId
                                   },
                                   {
                                       target.ApiConfiguration.PageParameterName, page.ToString( CultureInfo.InvariantCulture )
                                   },
                                   {
                                       target.ApiConfiguration.SortByParameterName, sortBy.ToTmdbParameter( target.ApiConfiguration )
                                   },
                                   {
                                       target.ApiConfiguration.SortOrderParameterName, sortOrder.ToTmdbParameter( target.ApiConfiguration )
                                   },
                                   {
                                       target.ApiConfiguration.LanguageParameterName, language
                                   }
                               } );
            Assert.IsNull( method );
        }

        /// <summary>
        ///     A test for GetAccountWatchListAsync
        /// </summary>
        [TestMethod]
        public async Task GetAccountWatchListAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var sessionId = Guid.NewGuid().ToString();
            var accountId = new Random().Next( 0, Int32.MaxValue );
            var page = new Random().Next( 0, Int32.MaxValue );
            const TmdbSortBy sortBy = TmdbSortBy.CreatedAt;
            var sortOrder = page % 2 == 0 ? TmdbSortOrder.Ascending : TmdbSortOrder.Descending;
            var language = Guid.NewGuid().ToString();

            await target.GetAccountWatchListAsync( accountId, sessionId, page, sortBy, sortOrder, language );

            CheckApiQuery( url, String.Format( target.ApiConfiguration.AccountWatchListMethodName, accountId ), target.ApiConfiguration,
                           new Dictionary<String, String>
                               {
                                   {
                                       target.ApiConfiguration.SessionIdParameterName, sessionId
                                   },
                                   {
                                       target.ApiConfiguration.PageParameterName, page.ToString( CultureInfo.InvariantCulture )
                                   },
                                   {
                                       target.ApiConfiguration.SortByParameterName, sortBy.ToTmdbParameter( target.ApiConfiguration )
                                   },
                                   {
                                       target.ApiConfiguration.SortOrderParameterName, sortOrder.ToTmdbParameter( target.ApiConfiguration )
                                   },
                                   {
                                       target.ApiConfiguration.LanguageParameterName, language
                                   }
                               } );
            Assert.IsNull( method );
        }

        #endregion Account

        #region Movies

        /// <summary>
        ///     A test for GetMovieAsync
        /// </summary>
        [TestMethod]
        public async Task GetMovieAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var movieId = new Random().Next( 0, Int32.MaxValue );
            var appendMethod = movieId % 2 == 0 ? TmdbMovieMethod.All : TmdbMovieMethod.Releases;
            var language = Guid.NewGuid().ToString();

            await target.GetMovieAsync( movieId, appendMethod, language );

            CheckApiQuery( url, String.Format( target.ApiConfiguration.GetMovieMethodName, movieId ), target.ApiConfiguration,
                           new Dictionary<string, string>
                               {
                                   {
                                       target.ApiConfiguration.AddToResponseParameterName, appendMethod.ToTmdbParameter( target.ApiConfiguration )
                                   },
                                   {
                                       target.ApiConfiguration.LanguageParameterName, language
                                   },
                               } );
            Assert.IsNull( method );
        }

        /// <summary>
        ///     A test for GetAlternativeMovieTitlesAsync
        /// </summary>
        [TestMethod]
        public async Task GetAlternativeMovieTitlesAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var movieId = new Random().Next( 0, Int32.MaxValue );
            var country = Guid.NewGuid().ToString();

            await target.GetAlternativeMovieTitlesAsync( movieId, country );

            CheckApiQuery( url, String.Format( target.ApiConfiguration.MovieAlternativeTitlesMethodName, movieId ), target.ApiConfiguration,
                           new Dictionary<string, string>
                               {
                                   {
                                       target.ApiConfiguration.CountryParameterName, country
                                   },
                               } );
            Assert.IsNull( method );
        }

        /// <summary>
        ///     A test for GetMovieCastAsync
        /// </summary>
        [TestMethod]
        public async Task GetMovieCastAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var movieId = new Random().Next( 0, Int32.MaxValue );

            await target.GetMovieCastAsync( movieId );

            CheckApiQuery( url, String.Format( target.ApiConfiguration.MovieCastMethodName, movieId ), target.ApiConfiguration );
            Assert.IsNull( method );
        }

        /// <summary>
        ///     A test for GetMovieImagesAsync
        /// </summary>
        [TestMethod]
        public async Task GetMovieImagesAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var movieId = new Random().Next( 0, Int32.MaxValue );
            var language = Guid.NewGuid().ToString();

            await target.GetMovieImagesAsync( movieId, language );

            CheckApiQuery( url, String.Format( target.ApiConfiguration.ImagesMethodName, movieId ), target.ApiConfiguration,
                           new Dictionary<string, string>
                               {
                                   {
                                       target.ApiConfiguration.LanguageParameterName, language
                                   }
                               } );
            Assert.IsNull( method );
        }

        /// <summary>
        ///     A test for GetMovieKeywordsAsync
        /// </summary>
        [TestMethod]
        public async Task GetMovieKeywordsAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var movieId = new Random().Next( 0, Int32.MaxValue );

            await target.GetMovieKeywordsAsync( movieId );

            CheckApiQuery( url, String.Format( target.ApiConfiguration.MovieKeywordsMethodName, movieId ), target.ApiConfiguration );
            Assert.IsNull( method );
        }

        /// <summary>
        ///     A test for GetMovieReleasesAsync
        /// </summary>
        [TestMethod]
        public async Task GetMovieReleasesAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var movieId = new Random().Next( 0, Int32.MaxValue );

            await target.GetMovieReleasesAsync( movieId );

            CheckApiQuery( url, String.Format( target.ApiConfiguration.MovieReleasesMethodName, movieId ), target.ApiConfiguration );
            Assert.IsNull( method );
        }

        /// <summary>
        ///     A test for GetMovieTrailersAsync
        /// </summary>
        [TestMethod]
        public async Task GetMovieTrailersAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var movieId = new Random().Next( 0, Int32.MaxValue );

            await target.GetMovieTrailersAsync( movieId );

            CheckApiQuery( url, String.Format( target.ApiConfiguration.MovieTrailersMethodName, movieId ), target.ApiConfiguration );
            Assert.IsNull( method );
        }

        /// <summary>
        ///     A test for GetMovieTranslationsAsync
        /// </summary>
        [TestMethod]
        public async Task GetMovieTranslationsAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var movieId = new Random().Next( 0, Int32.MaxValue );

            await target.GetMovieTranslationsAsync( movieId );

            CheckApiQuery( url, String.Format( target.ApiConfiguration.MovieTranslationsMethodName, movieId ), target.ApiConfiguration );
            Assert.IsNull( method );
        }

        /// <summary>
        ///     A test for GetSimilarMoviesAsync
        /// </summary>
        [TestMethod]
        public async Task GetSimilarMoviesAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var movieId = new Random().Next( 0, Int32.MaxValue );
            var page = new Random().Next( 0, Int32.MaxValue );
            var langauge = Guid.NewGuid().ToString();

            await target.GetSimilarMoviesAsync( movieId, page, langauge );

            CheckApiQuery( url, String.Format( target.ApiConfiguration.SimilarMoviesMethodName, movieId ), target.ApiConfiguration,
                           new Dictionary<string, string>
                               {
                                   {
                                       target.ApiConfiguration.LanguageParameterName, langauge
                                   },
                                   {
                                       target.ApiConfiguration.PageParameterName, page.ToString( CultureInfo.InvariantCulture )
                                   }
                               } );
            Assert.IsNull( method );
        }

        /// <summary>
        ///     A test for GetMovieReviewsAsync
        /// </summary>
        [TestMethod]
        public async Task GetMovieReviewsAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var movieId = new Random().Next( 0, Int32.MaxValue );
            var page = new Random().Next( 0, Int32.MaxValue );
            var langauge = Guid.NewGuid().ToString();

            await target.GetMovieReviewsAsync( movieId, page, langauge );

            CheckApiQuery( url, String.Format( target.ApiConfiguration.MovieReviewsMethodName, movieId ), target.ApiConfiguration,
                           new Dictionary<string, string>
                               {
                                   {
                                       target.ApiConfiguration.LanguageParameterName, langauge
                                   },
                                   {
                                       target.ApiConfiguration.PageParameterName, page.ToString( CultureInfo.InvariantCulture )
                                   }
                               } );
            Assert.IsNull( method );
        }

        /// <summary>
        ///     A test for GetMovieListsAsync
        /// </summary>
        [TestMethod]
        public async Task GetMovieListsAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var movieId = new Random().Next( 0, Int32.MaxValue );
            var page = new Random().Next( 0, Int32.MaxValue );
            var langauge = Guid.NewGuid().ToString();

            await target.GetMovieListsAsync( movieId, page, langauge );

            CheckApiQuery( url, String.Format( target.ApiConfiguration.MovieListsMethodName, movieId ), target.ApiConfiguration,
                           new Dictionary<string, string>
                               {
                                   {
                                       target.ApiConfiguration.LanguageParameterName, langauge
                                   },
                                   {
                                       target.ApiConfiguration.PageParameterName, page.ToString( CultureInfo.InvariantCulture )
                                   }
                               } );
            Assert.IsNull( method );
        }

        /// <summary>
        ///     A test for GetMovieChangesAsync
        /// </summary>
        [TestMethod]
        public async Task GetMovieChangesAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var movieId = new Random().Next( 0, Int32.MaxValue );
            var startDate = DateTime.Now.Subtract( TimeSpan.FromDays( new Random().Next( 10, 40 ) ) );
            var endDate = DateTime.Now;

            await target.GetMovieChangesAsync( movieId, startDate, endDate );

            CheckApiQuery( url, String.Format( target.ApiConfiguration.MovieChangesMethodName, movieId ), target.ApiConfiguration,
                           new Dictionary<string, string>
                               {
                                   {
                                       target.ApiConfiguration.StartDateParameterName, startDate.ToString( target.ApiConfiguration.JsonDatePattern )
                                   },
                                   {
                                       target.ApiConfiguration.EndDateParameterName, endDate.ToString( target.ApiConfiguration.JsonDatePattern )
                                   }
                               } );
            Assert.IsNull( method );
        }

        /// <summary>
        ///     A test for GetLatestMovieAsync
        /// </summary>
        [TestMethod]
        public async Task GetLatestMovieAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            await target.GetLatestMovieAsync();

            CheckApiQuery( url, target.ApiConfiguration.LatestMoviesMethodName, target.ApiConfiguration );
            Assert.IsNull( method );
        }

        /// <summary>
        ///     A test for GetUpcomingMoviesAsync
        /// </summary>
        [TestMethod]
        public async Task GetUpcomingMoviesAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var page = new Random().Next( 0, Int32.MaxValue );
            var langauge = Guid.NewGuid().ToString();

            await target.GetUpcomingMoviesAsync( page, langauge );

            CheckApiQuery( url, target.ApiConfiguration.UpcomingMethodName, target.ApiConfiguration, new Dictionary<string, string>
                {
                    {
                        target.ApiConfiguration.PageParameterName, page.ToString( CultureInfo.InvariantCulture )
                    },
                    {
                        target.ApiConfiguration.LanguageParameterName, langauge
                    }
                } );
            Assert.IsNull( method );
        }

        /// <summary>
        ///     A test for GetNowPlayingmoviesAsync
        /// </summary>
        [TestMethod]
        public async Task GetNowPlayingmoviesAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var page = new Random().Next( 0, Int32.MaxValue );
            var langauge = Guid.NewGuid().ToString();

            await target.GetNowPlayingmoviesAsync( page, langauge );

            CheckApiQuery( url, target.ApiConfiguration.NowPlayingMoviesMethodName, target.ApiConfiguration, new Dictionary<string, string>
                {
                    {
                        target.ApiConfiguration.PageParameterName, page.ToString( CultureInfo.InvariantCulture )
                    },
                    {
                        target.ApiConfiguration.LanguageParameterName, langauge
                    }
                } );
            Assert.IsNull( method );
        }

        /// <summary>
        ///     A test for GetPopularMoviesAsync
        /// </summary>
        [TestMethod]
        public async Task GetPopularMoviesAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var page = new Random().Next( 0, Int32.MaxValue );
            var langauge = Guid.NewGuid().ToString();

            await target.GetPopularMoviesAsync( page, langauge );

            CheckApiQuery( url, target.ApiConfiguration.PopularMethodName, target.ApiConfiguration, new Dictionary<string, string>
                {
                    {
                        target.ApiConfiguration.PageParameterName, page.ToString( CultureInfo.InvariantCulture )
                    },
                    {
                        target.ApiConfiguration.LanguageParameterName, langauge
                    }
                } );
            Assert.IsNull( method );
        }

        /// <summary>
        ///     A test for GetTopRatedMoviesAsync
        /// </summary>
        [TestMethod]
        public async Task GetTopRatedMoviesAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var page = new Random().Next( 0, Int32.MaxValue );
            var langauge = Guid.NewGuid().ToString();

            await target.GetTopRatedMoviesAsync( page, langauge );

            CheckApiQuery( url, target.ApiConfiguration.TopRatedMoviesMethodName, target.ApiConfiguration, new Dictionary<string, string>
                {
                    {
                        target.ApiConfiguration.PageParameterName, page.ToString( CultureInfo.InvariantCulture )
                    },
                    {
                        target.ApiConfiguration.LanguageParameterName, langauge
                    }
                } );
            Assert.IsNull( method );
        }

        /// <summary>
        ///     A test for GetMovieAccountStateAsync
        /// </summary>
        [TestMethod]
        public async Task GetMovieAccountStateAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var movieId = new Random().Next( 0, Int32.MaxValue );
            var sessionId = Guid.NewGuid().ToString();

            await target.GetMovieAccountStateAsync( movieId, sessionId );

            CheckApiQuery( url, String.Format( target.ApiConfiguration.MovieAccountStatesMethodName, movieId ), target.ApiConfiguration,
                           new Dictionary<string, string>
                               {
                                   {
                                       target.ApiConfiguration.SessionIdParameterName, sessionId
                                   }
                               } );
            Assert.IsNull( method );
        }

        /// <summary>
        ///     A test for RateMovieAsync
        /// </summary>
        [TestMethod]
        public async Task RateMovieAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var movieId = new Random().Next( 0, Int32.MaxValue );
            var ratingRequest = new TmdbMovieRatingRequest
                {
                    Value = 9
                };
            var sessionId = Guid.NewGuid().ToString();
            var guestSessionId = Guid.NewGuid().ToString();

            await target.RateMovieAsync( movieId, ratingRequest, sessionId, guestSessionId );

            CheckApiQuery( url, String.Format( target.ApiConfiguration.RatingMethodName, movieId ), target.ApiConfiguration,
                           new Dictionary<string, string>
                               {
                                   //{target.ApiConfiguration.GuestSessionIdParameterName, guestSessionId},
                                   {
                                       target.ApiConfiguration.SessionIdParameterName, sessionId
                                   }
                               } );
            Assert.IsNull( method );

            await target.RateMovieAsync( movieId, ratingRequest, guestSessionId: guestSessionId );

            CheckApiQuery( url, String.Format( target.ApiConfiguration.RatingMethodName, movieId ), target.ApiConfiguration,
                           new Dictionary<string, string>
                               {
                                   {
                                       target.ApiConfiguration.GuestSessionIdParameterName, guestSessionId
                                   },
                                   //{target.ApiConfiguration.SessionIdParameterName, sessionId}
                               } );
            Assert.IsNull( method );
        }

        #endregion Movies

        #region Collection

        /// <summary>
        ///     A test for GetCollectionAsync
        /// </summary>
        [TestMethod]
        public async Task GetCollectionAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var collectionId = new Random().Next( 0, Int32.MaxValue );
            const TmdbCollectionMethod appendMethod = TmdbCollectionMethod.Images;
            var language = Guid.NewGuid().ToString();

            await target.GetCollectionAsync( collectionId, appendMethod, language );

            CheckApiQuery( url, String.Format( target.ApiConfiguration.MovieCollectionMethodName, collectionId ), target.ApiConfiguration,
                           new Dictionary<string, string>
                               {
                                   {
                                       target.ApiConfiguration.LanguageParameterName, language
                                   },
                                   {
                                       target.ApiConfiguration.AddToResponseParameterName, appendMethod.ToTmdbParameter( target.ApiConfiguration )
                                   },
                               } );
            Assert.IsNull( method );
        }

        /// <summary>
        ///     A test for GetCollectionImagesAsync
        /// </summary>
        [TestMethod]
        public async Task GetCollectionImagesAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var collectionId = new Random().Next( 0, Int32.MaxValue );
            var language = Guid.NewGuid().ToString();

            await target.GetCollectionImagesAsync( collectionId, language );

            CheckApiQuery( url, String.Format( target.ApiConfiguration.MovieCollectionImageMethodName, collectionId ), target.ApiConfiguration,
                           new Dictionary<string, string>
                               {
                                   {
                                       target.ApiConfiguration.LanguageParameterName, language
                                   },
                               } );
            Assert.IsNull( method );
        }

        #endregion Collection

        #region Peopel

        /// <summary>
        ///     A test for GetPersonAsync
        /// </summary>
        [TestMethod]
        public async Task GetPersonAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var personId = new Random().Next( 0, Int32.MaxValue );
            var appendMethod = personId % 2 == 0 ? TmdbPersonMethod.Images : TmdbPersonMethod.All;

            await target.GetPersonAsync( personId, appendMethod );

            CheckApiQuery( url, String.Format( target.ApiConfiguration.GetPersonMethodName, personId ), target.ApiConfiguration,
                           new Dictionary<string, string>
                               {
                                   {
                                       target.ApiConfiguration.AddToResponseParameterName, appendMethod.ToTmdbParameter( target.ApiConfiguration )
                                   },
                               } );
            Assert.IsNull( method );
        }

        /// <summary>
        ///     A test for GetPersonCreditsAsync
        /// </summary>
        [TestMethod]
        public async Task GetPersonCreditsAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var personId = new Random().Next( 0, Int32.MaxValue );
            var language = Guid.NewGuid().ToString();

            await target.GetPersonCreditsAsync( personId, language );

            CheckApiQuery( url, String.Format( target.ApiConfiguration.PersonCreditsMethodName, personId ), target.ApiConfiguration,
                           new Dictionary<string, string>
                               {
                                   {
                                       target.ApiConfiguration.LanguageParameterName, language
                                   },
                               } );
            Assert.IsNull( method );
        }

        /// <summary>
        ///     A test for GetPersonImageAsync
        /// </summary>
        [TestMethod]
        public async Task GetPersonImageAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var personId = new Random().Next( 0, Int32.MaxValue );
            var language = Guid.NewGuid().ToString();

            await target.GetPersonImageAsync( personId );

            CheckApiQuery( url, String.Format( target.ApiConfiguration.PersonImagesMethodName, personId ), target.ApiConfiguration );
            Assert.IsNull( method );
        }

        /// <summary>
        ///     A test for GetPersonChangesAsync
        /// </summary>
        [TestMethod]
        public async Task GetPersonChangesAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var personId = new Random().Next( 0, Int32.MaxValue );
            var startDate = DateTime.Now.Subtract( TimeSpan.FromDays( new Random().Next( 10, 40 ) ) );
            var endDate = DateTime.Now;

            await target.GetPersonChangesAsync( personId, startDate, endDate );

            CheckApiQuery( url, String.Format( target.ApiConfiguration.PersonChangesMethodName, personId ), target.ApiConfiguration,
                           new Dictionary<string, string>
                               {
                                   {
                                       target.ApiConfiguration.StartDateParameterName, startDate.ToString( target.ApiConfiguration.JsonDatePattern )
                                   },
                                   {
                                       target.ApiConfiguration.EndDateParameterName, endDate.ToString( target.ApiConfiguration.JsonDatePattern )
                                   }
                               } );
            Assert.IsNull( method );
        }

        /// <summary>
        ///     A test for GetPopularPeopleAsync
        /// </summary>
        [TestMethod]
        public async Task GetPopularPersonsAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var page = new Random().Next( 0, Int32.MaxValue );

            await target.GetPopularPeopleAsync( page );

            CheckApiQuery( url, target.ApiConfiguration.PopularPeopleMethodName, target.ApiConfiguration, new Dictionary<string, string>
                {
                    {
                        target.ApiConfiguration.PageParameterName, page.ToString()
                    }
                } );
            Assert.IsNull( method );
        }

        /// <summary>
        ///     A test for GetLatestPersonAsync
        /// </summary>
        [TestMethod]
        public async Task GetLatestPersonAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            await target.GetLatestPersonAsync();

            CheckApiQuery( url, target.ApiConfiguration.LatestPersonMethodName, target.ApiConfiguration );
            Assert.IsNull( method );
        }

        #endregion Peopel

        #region List

        /// <summary>
        ///     A test for GetListAsync
        /// </summary>
        [TestMethod]
        public async Task GetListAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var listId = Guid.NewGuid().ToString();

            await target.GetListAsync( listId );

            CheckApiQuery( url, String.Format( target.ApiConfiguration.ListMethodName, listId ), target.ApiConfiguration );
            Assert.IsNull( method );
        }

        /// <summary>
        ///     A test for GetListStateAsync
        /// </summary>
        [TestMethod]
        public async Task GetListStateAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var listId = Guid.NewGuid().ToString();
            var movieId = new Random().Next( 0, Int32.MaxValue );

            await target.GetListStateAsync( listId, movieId );

            CheckApiQuery( url, String.Format( target.ApiConfiguration.ListStatusMethodName, listId ), target.ApiConfiguration,
                           new Dictionary<string, string>
                               {
                                   {
                                       target.ApiConfiguration.MovieIdParameterName, movieId.ToString()
                                   }
                               } );
            Assert.IsNull( method );
        }

        /// <summary>
        ///     A test for CreateMovieListAsync
        /// </summary>
        [TestMethod]
        public async Task CreateMovieListAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var sessionId = Guid.NewGuid().ToString();

            await target.CreateMovieListAsync( sessionId, new TmdbCreateMovieListRequest() );

            CheckApiQuery( url, target.ApiConfiguration.CreateMovieListMethodName, target.ApiConfiguration, new Dictionary<string, string>
                {
                    {
                        target.ApiConfiguration.SessionIdParameterName, sessionId
                    }
                } );
            Assert.IsNull( method );
        }

        /// <summary>
        ///     A test for AddItemToListAsync
        /// </summary>
        [TestMethod]
        public async Task AddItemToListAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var listId = Guid.NewGuid().ToString();
            var sessionId = Guid.NewGuid().ToString();

            await target.AddItemToListAsync( listId, new TmdbListItemRequest(), sessionId );

            CheckApiQuery( url, String.Format( target.ApiConfiguration.ListAddItemMethodName, listId ), target.ApiConfiguration,
                           new Dictionary<string, string>
                               {
                                   {
                                       target.ApiConfiguration.SessionIdParameterName, sessionId
                                   }
                               } );
            Assert.IsNull( method );
        }

        /// <summary>
        ///     A test for RemoveItemFromListAsync
        /// </summary>
        [TestMethod]
        public async Task RemoveItemFromListAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var listId = Guid.NewGuid().ToString();
            var sessionId = Guid.NewGuid().ToString();

            await target.RemoveItemFromListAsync( listId, new TmdbListItemRequest(), sessionId );

            CheckApiQuery( url, String.Format( target.ApiConfiguration.ListRemoveItemMethodName, listId ), target.ApiConfiguration,
                           new Dictionary<string, string>
                               {
                                   {
                                       target.ApiConfiguration.SessionIdParameterName, sessionId
                                   }
                               } );
            Assert.IsNull( method );
        }

        /// <summary>
        ///     A test for DeleteListAsync
        /// </summary>
        [TestMethod]
        public async Task DeleteListAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var listId = Guid.NewGuid().ToString();
            var sessionId = Guid.NewGuid().ToString();

            await target.DeleteListAsync( listId, sessionId );

            CheckApiQuery( url, String.Format( target.ApiConfiguration.DeleteListMethodName, listId ), target.ApiConfiguration,
                           new Dictionary<string, string>
                               {
                                   {
                                       target.ApiConfiguration.SessionIdParameterName, sessionId
                                   }
                               } );
            Assert.AreEqual( "DELETE", method );
        }

        #endregion List

        #region Companies

        /// <summary>
        ///     A test for GetCompanyAsync
        /// </summary>
        [TestMethod]
        public async Task GetCompanyAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var companyId = new Random().Next( 0, Int32.MaxValue );
            var append = TmdbCompanyMethod.Movies;

            await target.GetCompanyAsync( companyId, append );

            CheckApiQuery( url, String.Format( target.ApiConfiguration.CompanyMethodName, companyId ), target.ApiConfiguration,
                           new Dictionary<string, string>
                               {
                                   {
                                       target.ApiConfiguration.AddToResponseParameterName, append.ToTmdbParameter( target.ApiConfiguration )
                                   }
                               } );
            Assert.IsNull( method );
        }

        /// <summary>
        ///     A test for GetCompanyMoviesAsync
        /// </summary>
        [TestMethod]
        public async Task GetCompanyMoviesAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var companyId = new Random().Next( 0, Int32.MaxValue );
            var page = new Random().Next( 0, Int32.MaxValue );
            var language = Guid.NewGuid().ToString();

            await target.GetCompanyMoviesAsync( companyId, page, language );

            CheckApiQuery( url, String.Format( target.ApiConfiguration.CompanyMoviesMethodName, companyId ), target.ApiConfiguration,
                           new Dictionary<string, string>
                               {
                                   {
                                       target.ApiConfiguration.PageParameterName, page.ToString( CultureInfo.InvariantCulture )
                                   },
                                   {
                                       target.ApiConfiguration.LanguageParameterName, language
                                   }
                               } );
            Assert.IsNull( method );
        }

        #endregion Companies

        #region Genres

        /// <summary>
        ///     A test for GetGenresAsync
        /// </summary>
        [TestMethod]
        public async Task GetGenresAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var language = Guid.NewGuid().ToString();

            await target.GetGenresAsync( language );

            CheckApiQuery( url, target.ApiConfiguration.GenreListMethodName, target.ApiConfiguration, new Dictionary<string, string>
                {
                    {
                        target.ApiConfiguration.LanguageParameterName, language
                    }
                } );
            Assert.IsNull( method );
        }

        /// <summary>
        ///     A test for GetGenreMoviesAsync
        /// </summary>
        [TestMethod]
        public async Task GetGenreMoviesAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var genreId = new Random().Next( 0, Int32.MaxValue );
            var page = new Random().Next( 0, Int32.MaxValue );
            var language = Guid.NewGuid().ToString();
            var allMovies = genreId % 2 == 0;
            var includeAdult = genreId % 2 == 0;

            await target.GetGenreMoviesAsync( genreId, page, language, allMovies, includeAdult );

            CheckApiQuery( url, String.Format( target.ApiConfiguration.GenreMovieMethodName, genreId ), target.ApiConfiguration,
                           new Dictionary<string, string>
                               {
                                   {
                                       target.ApiConfiguration.PageParameterName, page.ToString( CultureInfo.InvariantCulture )
                                   },
                                   {
                                       target.ApiConfiguration.LanguageParameterName, language
                                   },
                                   {
                                       target.ApiConfiguration.IncludeAllMoviesParameterName, allMovies.ToString()
                                   },
                                   {
                                       target.ApiConfiguration.IncludeAdultParameterName, includeAdult.ToString()
                                   }
                               } );
            Assert.IsNull( method );
        }

        #endregion Genres

        #region Keywords

        /// <summary>
        ///     A test for GetKeywordAsync
        /// </summary>
        [TestMethod]
        public async Task GetKeywordAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var keywordId = new Random().Next( 0, Int32.MaxValue );

            await target.GetKeywordAsync( keywordId );

            CheckApiQuery( url, String.Format( target.ApiConfiguration.KeywordMethodName, keywordId ), target.ApiConfiguration );
            Assert.IsNull( method );
        }

        /// <summary>
        ///     A test for GetKeywordMoviesAsync
        /// </summary>
        [TestMethod]
        public async Task GetKeywordMoviesAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var keywordId = new Random().Next( 0, Int32.MaxValue );
            var page = new Random().Next( 0, Int32.MaxValue );
            var language = Guid.NewGuid().ToString();

            await target.GetKeywordMoviesAsync( keywordId, page, language );

            CheckApiQuery( url, String.Format( target.ApiConfiguration.KeywordMoviesMethodName, keywordId ), target.ApiConfiguration,
                           new Dictionary<string, string>
                               {
                                   {
                                       target.ApiConfiguration.PageParameterName, page.ToString( CultureInfo.InvariantCulture )
                                   },
                                   {
                                       target.ApiConfiguration.LanguageParameterName, language
                                   }
                               } );
            Assert.IsNull( method );
        }

        #endregion Keywords

        #region Discover

        /// <summary>
        ///     A test for DiscoverMoviesAsync
        /// </summary>
        [TestMethod]
        public async Task DiscoverMoviesAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var page = new Random().Next( 0, Int32.MaxValue );
            var language = Guid.NewGuid().ToString();
            var filter = new DisoveryFilter
                {
                    CertificationCountry = Guid.NewGuid().ToString(),
                    MaximumCertification = Guid.NewGuid().ToString(),
                    MinimumVoteCount = new Random().Next( 0, Int32.MaxValue ),
                    MaximumReleaseDate = DateTime.Now.Subtract( TimeSpan.FromDays( 1 ) ),
                    PrimaryReleaseYear = new Random().Next( 0, Int32.MaxValue ),
                    MinimumAverageVotet = new Random().Next( 0, Int32.MaxValue ),
                    Year = new Random().Next( 0, Int32.MaxValue ),
                    MinimumReleaseDate = DateTime.Now,
                    IncludeAdult = new Random().Next( 0, Int32.MaxValue ) % 2 == 0,
                    SortBy = TmdbDiscoverySortBy.PopularityAsc,
                    GenreFilter = new GenreFilter
                        {
                            Operator = TmdbFilterOperator.And,
                            Genres = new List<Int32>
                                {
                                    1,
                                    2,
                                    3,
                                    new Random().Next( 0, Int32.MaxValue )
                                }
                        },
                    Companies = new List<Int32>
                        {
                            1,
                            2,
                            3,
                            new Random().Next( 0, Int32.MaxValue )
                        }
                };

            await target.DiscoverMoviesAsync( page, language, filter );

            CheckApiQuery( url, target.ApiConfiguration.DiscoverMethodName, target.ApiConfiguration,
                           new Dictionary<string, string>
                               {
                                   {
                                       target.ApiConfiguration.PageParameterName, page.ToString( CultureInfo.InvariantCulture )
                                   },
                                   {
                                       target.ApiConfiguration.LanguageParameterName, language
                                   },
                                   {
                                       target.ApiConfiguration.CertificationCountryParameterName, filter.CertificationCountry
                                   },
                                   {
                                       target.ApiConfiguration.IncludeAdultParameterName, filter.IncludeAdult.ToString()
                                   },
                                   {
                                       target.ApiConfiguration.YearParameterName, filter.Year.ToString()
                                   },
                                   {
                                       target.ApiConfiguration.MinimumVoteCountParameterName, filter.MinimumVoteCount.ToString()
                                   },
                                   {
                                       target.ApiConfiguration.MinimumVoteAverageParameterName, filter.MinimumAverageVotet.ToString()
                                   },
                                   {
                                       target.ApiConfiguration.PrimaryReleaseYearParameterName, filter.PrimaryReleaseYear.ToString()
                                   },
                                   {
                                       target.ApiConfiguration.MinimumReleaseDateParameterName,
                                       ( ( DateTime ) filter.MinimumReleaseDate ).ToString( target.ApiConfiguration.JsonDatePattern )
                                   },
                                   {
                                       target.ApiConfiguration.MaximumReleaseDateParameterName,
                                       ( ( DateTime ) filter.MaximumReleaseDate ).ToString( target.ApiConfiguration.JsonDatePattern )
                                   },
                                   {
                                       target.ApiConfiguration.MaximumCertificationParameterName, filter.MaximumCertification
                                   },
                                   {
                                       target.ApiConfiguration.WithCompaniesParameterName, filter.Companies.Select( x => x.ToString() )
                                                                                                 .Aggregate(
                                                                                                     ( current, x ) =>
                                                                                                     String.Concat( current,
                                                                                                                    target.ApiConfiguration.AndChar, x ) )
                                   },

                                   {
                                       target.ApiConfiguration.DiscoverySortByParameterName, filter.SortBy.ToTmdbParameter( target.ApiConfiguration )
                                   },

                                   {
                                       target.ApiConfiguration.WithGenresParameterName,
                                       filter.GenreFilter.Genres.Select( x => x.ToString( CultureInfo.InvariantCulture ) ).Aggregate(
                                           ( current, x ) =>
                                           String.Concat( current,
                                                          filter.GenreFilter.Operator == TmdbFilterOperator.And
                                                              ? target.ApiConfiguration.AndChar
                                                              : target.ApiConfiguration.OrChar, x ) )
                                   },
                               } );

            Assert.IsNull( method );
        }

        #endregion Discover

        #region Search

        /// <summary>
        ///     A test for SearchMovieAsync
        /// </summary>
        [TestMethod]
        public async Task SearchMovieAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var query = Guid.NewGuid().ToString();
            var page = new Random().Next( 0, Int32.MaxValue );
            var language = Guid.NewGuid().ToString();
            var includeAdult = page % 2 == 0;
            var year = new Random().Next( 0, Int32.MaxValue );
            var primaryReleaseYear = new Random().Next( 0, Int32.MaxValue );
            var searchType = page % 2 == 0 ? TmdbSearchType.Ngram : TmdbSearchType.Phrase;

            await target.SearchMovieAsync( query, page, language, includeAdult, year, primaryReleaseYear, searchType );

            CheckApiQuery( url, target.ApiConfiguration.SearchMovieMethodName, target.ApiConfiguration,
                           new Dictionary<string, string>
                               {
                                   {
                                       target.ApiConfiguration.PageParameterName, page.ToString( CultureInfo.InvariantCulture )
                                   },
                                   {
                                       target.ApiConfiguration.LanguageParameterName, language
                                   },

                                   {
                                       target.ApiConfiguration.QueryParameterName, query
                                   },
                                   {
                                       target.ApiConfiguration.IncludeAdultParameterName, includeAdult.ToString()
                                   },
                                   {
                                       target.ApiConfiguration.YearParameterName, year.ToString( CultureInfo.InvariantCulture )
                                   },
                                   {
                                       target.ApiConfiguration.PrimaryReleaseYearParameterName,
                                       primaryReleaseYear.ToString( CultureInfo.InvariantCulture )
                                   },
                                   {
                                       target.ApiConfiguration.SearchTypeParameterName, searchType.ToTmdbParameter( target.ApiConfiguration )
                                   },
                               } );

            Assert.IsNull( method );
        }

        /// <summary>
        ///     A test for SearchMovieCollectionAsync
        /// </summary>
        [TestMethod]
        public async Task SearchMovieCollectionAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var query = Guid.NewGuid().ToString();
            var page = new Random().Next( 0, Int32.MaxValue );
            var language = Guid.NewGuid().ToString();

            await target.SearchMovieCollectionAsync( query, page, language );

            CheckApiQuery( url, target.ApiConfiguration.SearchCollectionMethodName, target.ApiConfiguration,
                           new Dictionary<string, string>
                               {
                                   {
                                       target.ApiConfiguration.PageParameterName, page.ToString( CultureInfo.InvariantCulture )
                                   },
                                   {
                                       target.ApiConfiguration.LanguageParameterName, language
                                   },

                                   {
                                       target.ApiConfiguration.QueryParameterName, query
                                   },
                               } );

            Assert.IsNull( method );
        }

        /// <summary>
        ///     A test for SearchPersonAsync
        /// </summary>
        [TestMethod]
        public async Task SearchPersonAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var query = Guid.NewGuid().ToString();
            var page = new Random().Next( 0, Int32.MaxValue );
            var includeAdult = page % 2 == 0;
            var searchType = page % 2 == 0 ? TmdbSearchType.Ngram : TmdbSearchType.Phrase;

            await target.SearchPersonAsync( query, page, includeAdult, searchType );

            CheckApiQuery( url, target.ApiConfiguration.SearchPersonMethodName, target.ApiConfiguration,
                           new Dictionary<string, string>
                               {
                                   {
                                       target.ApiConfiguration.PageParameterName, page.ToString( CultureInfo.InvariantCulture )
                                   },
                                   {
                                       target.ApiConfiguration.IncludeAdultParameterName, includeAdult.ToString()
                                   },

                                   {
                                       target.ApiConfiguration.QueryParameterName, query
                                   },
                                   {
                                       target.ApiConfiguration.SearchTypeParameterName, searchType.ToTmdbParameter( target.ApiConfiguration )
                                   },
                               } );

            Assert.IsNull( method );
        }

        /// <summary>
        ///     A test for SearchListAsync
        /// </summary>
        [TestMethod]
        public async Task SearchListAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var query = Guid.NewGuid().ToString();
            var page = new Random().Next( 0, Int32.MaxValue );
            var includeAdult = page % 2 == 0;

            await target.SearchListAsync( query, page, includeAdult );

            CheckApiQuery( url, target.ApiConfiguration.SearchListMethodName, target.ApiConfiguration,
                           new Dictionary<string, string>
                               {
                                   {
                                       target.ApiConfiguration.PageParameterName, page.ToString( CultureInfo.InvariantCulture )
                                   },
                                   {
                                       target.ApiConfiguration.IncludeAdultParameterName, includeAdult.ToString()
                                   },

                                   {
                                       target.ApiConfiguration.QueryParameterName, query
                                   }
                               } );

            Assert.IsNull( method );
        }

        /// <summary>
        ///     A test for SearchCompanyAsync
        /// </summary>
        [TestMethod]
        public async Task SearchCompanyAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var query = Guid.NewGuid().ToString();
            var page = new Random().Next( 0, Int32.MaxValue );

            await target.SearchCompanyAsync( query, page );

            CheckApiQuery( url, target.ApiConfiguration.SearchCompanyMethodName, target.ApiConfiguration,
                           new Dictionary<string, string>
                               {
                                   {
                                       target.ApiConfiguration.PageParameterName, page.ToString( CultureInfo.InvariantCulture )
                                   },
                                   {
                                       target.ApiConfiguration.QueryParameterName, query
                                   }
                               } );

            Assert.IsNull( method );
        }

        /// <summary>
        ///     A test for SearchKeywordAsync
        /// </summary>
        [TestMethod]
        public async Task SearchKeywordAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var query = Guid.NewGuid().ToString();
            var page = new Random().Next( 0, Int32.MaxValue );

            await target.SearchKeywordAsync( query, page );

            CheckApiQuery( url, target.ApiConfiguration.SearchKeywordMethodName, target.ApiConfiguration,
                           new Dictionary<string, string>
                               {
                                   {
                                       target.ApiConfiguration.PageParameterName, page.ToString( CultureInfo.InvariantCulture )
                                   },
                                   {
                                       target.ApiConfiguration.QueryParameterName, query
                                   }
                               } );

            Assert.IsNull( method );
        }

        #endregion Search

        #region Review

        /// <summary>
        ///     A test for GetReviewAsync
        /// </summary>
        [TestMethod]
        public async Task GetReviewAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var reviewId = Guid.NewGuid().ToString();

            await target.GetReviewAsync( reviewId );

            CheckApiQuery( url, String.Format( target.ApiConfiguration.ReviewMethodName, reviewId ), target.ApiConfiguration );

            Assert.IsNull( method );
        }

        #endregion Review

        #region Changes

        /// <summary>
        ///     A test for GetChangedMoviesAsync
        /// </summary>
        [TestMethod]
        public async Task GetChangedMoviesAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var startDate = DateTime.Now.Subtract( TimeSpan.FromDays( 10 ) );
            var endDate = DateTime.Now;

            await target.GetChangedMoviesAsync( startDate, endDate );

            CheckApiQuery( url, target.ApiConfiguration.ChangedMoviesMethodName, target.ApiConfiguration, new Dictionary<string, string>
                {
                    {
                        target.ApiConfiguration.StartDateParameterName, startDate.ToString( target.ApiConfiguration.JsonDatePattern )
                    },
                    {
                        target.ApiConfiguration.EndDateParameterName, endDate.ToString( target.ApiConfiguration.JsonDatePattern )
                    }
                } );

            Assert.IsNull( method );
        }

        /// <summary>
        ///     A test for GetChangedPeopleAsync
        /// </summary>
        [TestMethod]
        public async Task GetChangedPeopleAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );
            var startDate = DateTime.Now.Subtract( TimeSpan.FromDays( 10 ) );
            var endDate = DateTime.Now;

            await target.GetChangedPeopleAsync( startDate, endDate );

            CheckApiQuery( url, target.ApiConfiguration.ChangedPeopleMethodName, target.ApiConfiguration, new Dictionary<string, string>
                {
                    {
                        target.ApiConfiguration.StartDateParameterName, startDate.ToString( target.ApiConfiguration.JsonDatePattern )
                    },
                    {
                        target.ApiConfiguration.EndDateParameterName, endDate.ToString( target.ApiConfiguration.JsonDatePattern )
                    }
                } );

            Assert.IsNull( method );
        }

        #endregion Changes

        #region Jobs

        /// <summary>
        ///     A test for GetJobsAsync
        /// </summary>
        [TestMethod]
        public async Task GetJobsAsyncTest()
        {
            var url = String.Empty;
            var method = String.Empty;

            var target = GetTarget( ( u, m ) =>
                {
                    url = u;
                    method = m;
                } );

            await target.GetJobsAsync();

            CheckApiQuery( url, target.ApiConfiguration.JobsMethodName, target.ApiConfiguration );

            Assert.IsNull( method );
        }

        #endregion Jobs

        /*

        /// <summary>
        ///     A test for ApiClient
        /// </summary>
        [TestMethod]
        public async Task ApiClientTest()
        {
            var target = new ApiWrapper();
            IApiClient expected = null;
            IApiClient actual;
            target.ApiClient = expected;
            actual = target.ApiClient;
            Assert.AreEqual( expected, actual );
        }

        /// <summary>
        ///     A test for ApiConfiguration
        /// </summary>
        [TestMethod]
        public async Task ApiConfigurationTest()
        {
            var target = new ApiWrapper();
            IApiConfiguration expected = null;
            IApiConfiguration actual;
            target.ApiConfiguration = expected;
            actual = target.ApiConfiguration;
            Assert.AreEqual( expected, actual );
        }*/
    }
}